package com.ticket.sass.admin.manager.wx

import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage
import cn.binarywang.wx.miniapp.constant.WxMaConstants
import com.ticket.sass.admin.config.AppConfigurer
import com.ticket.sass.admin.config.WxMaServiceConfigurer
import me.chanjar.weixin.common.error.WxErrorException
import mu.KotlinLogging
import org.springframework.stereotype.Component


/**
 * 微信小程序订阅消息服务
 *
 * @property wxMaServiceConfigurer 微信小程序服务配置
 * @property appConfigurer 应用配置
 *
 * @author 朱其鹏
 * @date 2024/6/7 14:45
 */
@Component
class WxaMessageManager(
    private val wxMaServiceConfigurer: WxMaServiceConfigurer,
    private val appConfigurer: AppConfigurer,
) {
    data class OrderCommodityDispatchTpl(
        val takeCode: String,
        val place: String,
        val commodityInfo: String,
        val createdTime: String,
        val tips: String,
    )

    private val logger = KotlinLogging.logger {}


    /**
     * 卖品配送通知
     *
     * @param id 卖品订单ID，orders.id
     * @param cinemaId 影院ID
     * @param openId 接收消息的用户的微信OpenID
     * @param tplData 后付费通知订阅消息的数据
     *
     * @throws WxErrorException 如果发送消息失败
     */
    fun orderCommodityDispatch(id: Long, cinemaId: Long, openId: String, tplData: OrderCommodityDispatchTpl) {
        sendSubscribeMessage(
            openId,
            appConfigurer.wx.miniapp.subscribeMessage.tplIdOrderCommodityDispatch,
            "/page_sku/shoporderdetails/shoporderdetails?id=$id&cinemaId=$cinemaId",
            listOf(
                WxMaSubscribeMessage.MsgData("character_string1", tplData.takeCode),
                WxMaSubscribeMessage.MsgData("short_thing12", tplData.place),
                WxMaSubscribeMessage.MsgData("thing2", tplData.commodityInfo.truncate(20)),
                WxMaSubscribeMessage.MsgData("time3", tplData.createdTime),
                WxMaSubscribeMessage.MsgData("thing5", tplData.tips)
            ),
            tplData
        )
    }

    /**
     * 发送微信小程序订阅消息的通用方法
     *
     * @param openId 接收消息的用户的微信OpenID
     * @param templateId 订阅消息模板ID
     * @param page 订阅消息跳转的页面路径
     * @param data 订阅消息的数据
     * @param tplData 订阅消息的模板数据（用于日志记录）
     *
     * @throws WxErrorException 如果发送消息失败
     */
    private fun sendSubscribeMessage(
        openId: String,
        templateId: String,
        page: String,
        data: List<WxMaSubscribeMessage.MsgData>,
        tplData: Any
    ) {
        try {
            wxMaServiceConfigurer.build().msgService.sendSubscribeMsg(WxMaSubscribeMessage(
                openId,
                templateId,
                page,
                data,
                appConfigurer.wx.miniapp.subscribeMessage.miniprogramState,
                WxMaConstants.MiniProgramLang.ZH_CN
            ))
            logger.info { "订阅消息发送成功，data：$tplData" }
        } catch (e: WxErrorException) {
            logger.error(e) { "订阅消息发送失败，data：$tplData" }
        }
    }

    /**
     * 截断字符串并在末尾添加指定字符。
     *
     * @param maxLength 允许的最大长度
     * @param suffix 要添加到截断字符串末尾的字符，默认为 "..."
     *
     * @return 如果字符串长度超过 maxLength，则返回截断并拼接后缀的字符串；否则返回原字符串
     */
    fun String.truncate(maxLength: Int, suffix: String = "..."): String {
        // 检查 maxLength 是否小于 suffix 的长度，防止无限循环
        require(maxLength >= suffix.length) { "maxLength 必须大于或等于后缀的长度" }

        // 如果字符串长度超过 maxLength，则截断并拼接 suffix，否则返回原字符串
        return if (this.length > maxLength) {
            this.take(maxLength - suffix.length) + suffix
        } else {
            this
        }
    }
}